/* 
 * File:   EntityCreator.cpp
 * Author: RedEyedKiller
 * 
 * Created on 26 Σεπτέμβριος 2010, 4:28 μμ
 */

#include "parsers/EntityParser.h"
#include "EntityCreator.h"
#include "DrawLogic.h"
#include "Entity.h"
#include <string>

namespace EntitySystem
{

EntityCreator::EntityCreator()
{
    parser = new FileParser::EntityParser( this, ".xml" );
}

EntityCreator::~EntityCreator()
{
    delete parser;
    ResetCache( );
}

/**
 * @brief Returns a new entity as described in its script.
 * @param key - The name of the entity (script) to be created.
 * @return The new entity.
 */
Entity* EntityCreator::CreateEntity(const std::string& key)
{
    std::map<std::string, Entity*>::iterator it = prototypes.find( key );
    if( it == prototypes.end( ) )//parse the entity
    {
        Entity* e = new Entity;
        //the child is left empty 
        if( parser->ParseEntity( &e, key, "" ) )
        {
            prototypes[key] = e;
            return new Entity( *e );
        }
        delete e;
        return NULL;
    }
    else//entity found
    {
        return new Entity( *( it->second ) );
    }
}

/**
 * @brief Returns a new entity as described in its script.
 * @param key - The name of the entity (script) to be created.
 * @return The new entity.
 */
Entity* EntityCreator::CreateEntity(const std::string& key, const std::string& child)
{
    std::map<std::string, Entity*>::iterator it = prototypes.find( key );
    if( it == prototypes.end( ) )//parse the entity
    {
        Entity* e = new Entity;
        if( parser->ParseEntity( &e, key, child ) )
        {
            prototypes[key] = e;
            return new Entity( *e );
        }
        delete e;
        return NULL;
    }
    else//entity found
    {
        return new Entity( *( it->second ) );
    }
}

/**
 * Returns true if key has already been asigned to a value.
 * @param key
 * @return 
 */
bool EntityCreator::CheckPrototype(const std::string& key)
{
    return(prototypes.end( ) != prototypes.find( key ) );
}

/**
 * Registers the given entity as a prototype to be created later via CreateEntity.
 * @param prototype
 * @param key
 * @return 
 */
bool EntityCreator::RegisterEntityPrototype(Entity* prototype, const std::string& key)
{
    std::map<std::string, Entity*>::iterator it = prototypes.find( key );
    if( it == prototypes.end( ) )//its safe to insert the prototype.
    {
        prototypes[key] = prototype;
        return true;
    }
    else//entity found cannot re-insert it.
    {
        return false;
    }
}

/**
 * Deletes all prototypes cached. Most common use between diferent levels which
 * use different Entities.
 */
void EntityCreator::ResetCache()
{
    SafeRelease<std::string, Entity*>( prototypes );
}

}
